/////////////////////////////////////////////////////////////////////////////
//
// CodeLib.cpp
//
// Author : L.F.
// Date   : 2006.10.24
//
/////////////////////////////////////////////////////////////////////////////

#include "StdAfx.h"
#include "CodeLib.h"

/////////////////////////////////////////////////////////////////////////////
// CCodeLib

/////////////////////////////////////////////////////////////////////////////
// CCodeLib constructor and destructor

CCodeLib::CCodeLib()
{
}

CCodeLib::~CCodeLib()
{
}

/////////////////////////////////////////////////////////////////////////////
// Implementation

void CCodeLib::UTF8ToUnicode( WCHAR* pwchOut, const char* pchIn )
{
	char* pchTmp = ( char* ) pwchOut;

	pchTmp[ 1 ] = ( ( pchIn[ 0 ] & 0x0F ) << 4 ) + ( ( pchIn[ 1 ] >> 2 ) & 0x0F );
	pchTmp[ 0 ] = ( ( pchIn[ 1 ] & 0x03 ) << 6 ) + ( pchIn[ 2 ] & 0x3F );
}

void CCodeLib::UnicodeToGB2312( char* pchOut, unsigned short uData )
{
	::WideCharToMultiByte( CP_ACP, NULL, (LPCWSTR)& uData, 1, pchOut, sizeof( WCHAR ), NULL, NULL );
}

void CCodeLib::UTF8ToGB2312( std::string& strOut, const char* pchIn, int nLen )
{
	// The UTF-8 size is 3 bytes each character...
	//  note here.
	//  when It's asii code. It need to allocate more than one byte in the buffer...
	char* pBuffer = new char[ nLen + 1 ];
	ZeroMemory( pBuffer, nLen );
	ASSERT( pBuffer != NULL );
	if ( pBuffer == NULL )
		return;

	char chTmp[ 4 ];
	ZeroMemory( chTmp, sizeof( chTmp ) );

	int i = 0;
	int j = 0;

	while ( i < nLen )
	{
		if ( pchIn[ i ] > 0 )
		{
			pBuffer[ j++ ] = pchIn[ i++ ];
		}
		else
		{
			WCHAR wchTmp;
			UTF8ToUnicode( & wchTmp, pchIn + i );
			UnicodeToGB2312( chTmp, wchTmp );

			pBuffer[ j     ] = chTmp[ 0 ];
			pBuffer[ j + 1 ] = chTmp[ 1 ];

			i += 3;
			j += 2;
		}
	} // End loop
	pBuffer[ j ] = '\0';
	strOut = pBuffer;

	ASSERT( pBuffer != NULL );
	delete [] pBuffer;
}

void CCodeLib::GB2312ToUTF8( std::string& strOut, const char* pchIn, int nLen )
{
	char buf[ 4 ];
	char* pTmp = new char[ nLen + ( nLen >> 2 ) + 3 ];

	ZeroMemory( buf, 4 );
	ZeroMemory( pTmp, nLen + ( nLen >> 2 ) + 3 );

	int i = 0;
	int j = 0;

	while ( i < nLen )
	{
		if ( *( pchIn + i ) >= 0 )
		{
			pTmp[ j++ ] = pchIn[ i++ ];
		}
		else
		{
			WCHAR wch;
			GB2312ToUnicode( & wch, pchIn + i );

			UnicodeToUTF8( buf, & wch );

			unsigned short int nTmp = 0;
			nTmp = pTmp[ j     ] = buf[ 0 ];
			nTmp = pTmp[ j + 1 ] = buf[ 1 ];
			nTmp = pTmp[ j + 2 ] = buf[ 2 ];

			j += 3;
			i += 2;
		}
	}

	pTmp[ j ] = '\0';
	strOut = pTmp;
	delete [] pTmp;
}

void CCodeLib::GB2312ToUnicode( WCHAR* pwchOut, const char* pchIn )
{
	::MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, pchIn, 2, pwchOut, 1 );
}

void CCodeLib::UnicodeToUTF8( char* pchOut, WCHAR* pwchIn )
{
	char* pTmp = ( char* ) pwchIn;

	pchOut[ 0 ] = ( 0xE0 | ( ( pTmp[ 1 ] & 0xF0 ) >> 4 ) );
	pchOut[ 1 ] = ( 0x80 | ( ( pTmp[ 1 ] & 0x0F ) << 2 ) ) + ( ( pTmp[ 0 ] & 0xC0 ) >> 6 );
	pchOut[ 2 ] = ( 0x80 | ( pTmp[ 0 ] & 0x3F ) );
}

std::string CCodeLib::GetFileName( string strFilePath )
{
	string strFileName;
	string::iterator iter=strFilePath.end()-1;
	for(;iter!=strFilePath.begin();--iter){
		if((*iter)=='/'||(*iter)=='\\')
			break;
	}
	++iter;
	for(;iter!=strFilePath.end();++iter){
		strFileName.push_back(*iter);
	}

	return strFileName;
}
